home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / Snippets / Platforms & Tools / ◊Other / TRandom 1.0b3 / Random.cp < prev    next >
Encoding:
Text File  |  1991-11-04  |  12.1 KB  |  474 lines  |  [TEXT/MPS ]

  1. /*
  2.     Apple Macintosh Developer Technical Support, 
  3.     TRandom 1.0 -  Saturday, October 5, 1991 18:26:35
  4.  
  5.     TRandom.cp    -    C++ source
  6.  
  7.     Copyright © 1991 Apple Computer, Inc. 
  8.     All rights reserved.
  9.  
  10.     TRandom is a stackbased utility class for random number generation.
  11.     TRandom.cp contains the member function implementations for TRandom.
  12. */
  13.  
  14. // INCLUDE FILES -----------------------------------------------------------------------
  15.  
  16. #include "Random.h"
  17.  
  18.  
  19. // CLASS MEMBER FUNCTIONS IMPLEMENTATIONS ----------------------------------------------
  20.  
  21. // GENERAL -----------------------------------------------------------------------------
  22.  
  23. TRandom::TRandom(eRandType theType, long theSeed, 
  24.                     unsigned short low, unsigned short high)
  25. {
  26.     if(theSeed == 1)                                // no seed value
  27.         this->ShuffleSeed();                        // no first value, random value
  28.     else
  29.         this->SetSeedValue(theSeed);                // programmer defined seed    
  30.  
  31.     this->fLow      = low;
  32.     this->fHigh     = high;
  33.     this->fRange     = high - low;
  34.     
  35.     Boolean fState = this->IRandom(theType);        // initialize the object
  36. }
  37.  
  38.  
  39. TRandom::TRandom(const TRandom& other)                // copy constructor
  40. {
  41.     register int x;
  42.  
  43.     // fill in the needed fields with values from the referenced object
  44.     
  45.     this->fGenerator = other.fGenerator;
  46.     this->fAlgorithm = other.fAlgorithm;
  47.     this->fLow       = other.fLow;
  48.     this->fHigh      = other.fHigh;
  49.     this->fRange     = other.fRange;
  50.     this->fSeed      = other.fSeed;
  51.     this->fState     = other.fState;
  52.     this->fPrevNum   = other.fPrevNum;
  53.  
  54.     for(x = 0; x < eSHUFFLETABLE; x++)                // copy the values from array
  55.         this->fShuffleBuf[x] = other.fShuffleBuf[x];
  56. }
  57.  
  58.  
  59. TRandom& TRandom::operator=(const TRandom& other)    // assignment operator
  60. {
  61.     register int x;
  62.  
  63.     // fill in the needed fields with values from the referenced object
  64.  
  65.     this->fGenerator = other.fGenerator;
  66.     this->fAlgorithm = other.fAlgorithm;
  67.     this->fLow       = other.fLow;
  68.     this->fHigh      = other.fHigh;
  69.     this->fRange     = other.fRange;
  70.     this->fSeed      = other.fSeed;
  71.     this->fState     = other.fState;
  72.     this->fPrevNum   = other.fPrevNum;
  73.  
  74.     for(x = 0; x < eSHUFFLETABLE; x++)                // copy the values from array
  75.         this->fShuffleBuf[x] = other.fShuffleBuf[x];
  76.     
  77.     return *this;
  78. }
  79.  
  80.  
  81. TRandom::~TRandom(){}                                // virtual destructor, should 
  82.                                                     // *not* be inlined
  83.  
  84.  
  85. Boolean TRandom::IRandom(eRandType theType)
  86. {
  87.     switch(theType){
  88.         case MACOS:
  89.             qd.randSeed = this->GetSeedValue();
  90.             this->fGenerator = &TRandom::MacRandom;    // quick init
  91.             this->fAlgorithm = MACOS;
  92.             break;
  93.         case QUICK:
  94.             this->ShuffleSeed();
  95.             qd.randSeed = this->GetSeedValue();
  96.             this->fGenerator = &TRandom::QuickRandom;
  97.             this->fAlgorithm = QUICK;
  98.             break;
  99.         case SHUFFLE:
  100.             qd.randSeed = this->GetSeedValue();
  101.             this->fGenerator = &TRandom::ShuffleRandom;
  102.             this->fAlgorithm = SHUFFLE;
  103.             this->InitShuffleRandom();
  104.             break;
  105.         case PM:
  106.             this->fGenerator = &TRandom::ParkMiller;
  107.             this->fAlgorithm = PM;
  108.             break;
  109.         default:
  110.             return false;                            // should never get here...
  111.     };
  112.     return true;
  113. }
  114.  
  115.  
  116. // MAC TOOLBOX TRAP MEMBER FUNCTIONS ---------------------------------------------------
  117. unsigned short TRandom::MacRandom()                    // Toolbox random number generator
  118. {
  119.     register unsigned short temp;
  120.  
  121.     temp = short(Random());                            // scale to  0 - 65536
  122.     
  123.     return( ( (temp * this->fRange) /e16BIT) + this->fLow);
  124. }
  125.  
  126.  
  127. // ASSEMBER QUICK ROUTINE MEMBER FUNCTIONS --------------------------------------------
  128.  
  129. unsigned short TRandom::QuickRandom()                // quick asm random generator
  130. {
  131.     register unsigned short temp;
  132.  
  133.     temp = short(AsmRandom());                        // scale to  0 - 65536
  134.     
  135.     return( ( (temp * this->fRange) /e16BIT) + this->fLow);
  136. }
  137.  
  138.  
  139. // SHUFFLE RANDOM MEMBER FUNCTIONS ----------------------------------------------------
  140.  
  141. TRandom& TRandom::InitShuffleRandom()
  142. {
  143.     register short i;
  144.  
  145.     for(i = 0; i < eSHUFFLETABLE; i++)
  146.         Random();                                    // shuffle the random generator
  147.     for(i = 0; i < eSHUFFLETABLE; i++)
  148.         this->fShuffleBuf[i] = Random();            // fill the buffer
  149.     
  150.     this->fPrevNum = Random();                        // get first 'later' value
  151.     return *this;
  152. }
  153.  
  154.  
  155. unsigned short TRandom::ShuffleRandom()
  156. {
  157.     register unsigned short index;
  158.     
  159.     index = (this->fPrevNum * eSHUFFLETABLE) /e16BIT;
  160.     this->fPrevNum = this->fShuffleBuf[index];        // get random number from table
  161.     this->fShuffleBuf[index] = Random();            // new random table entry
  162.  
  163.     return( ( (this->fPrevNum * this->fRange) /e16BIT) + this->fLow);
  164. }
  165.  
  166.  
  167.  
  168. // PARK&MILLER MEMBER FUNCTIONS -------------------------------------------------------
  169.  
  170. unsigned short TRandom::ParkMiller()                // CACM Oct 1988
  171. {
  172.     unsigned short                high, low;
  173.     register unsigned  short    temp;
  174.     
  175.     high = short (this->fSeed / ePM3);
  176.     low  = short (this->fSeed % ePM3);
  177.     temp = (ePM2 * low) - (ePM1 * high);
  178.     
  179.     if( temp > 0 )
  180.         this->fSeed = temp;
  181.     else
  182.         this->fSeed = temp + eACM_MAX;
  183.  
  184.     return( ( (temp * this->fRange) /e16BIT) + this->fLow);
  185. }
  186.  
  187. //    TEST FUNCTIONS --------------------------------------------------------------------
  188.  
  189. /*     This is the TestRandomClass test suite:
  190.     
  191.     1. create an instance of the TGenerator class, and produce a random
  192.     number with each included algorithm
  193.     2. CreatecBIGNUMamount random numbers with each algorithm, and count the time
  194.     3. Create twice x amount random numbers from the same seed, and compare
  195.     if the values are the same.
  196.     4. Test mutator class reference passing (syntax check)    
  197.     5. Test of copy constructor
  198.     6. Test of assignment operator overload
  199.     
  200.     Notes:
  201.     Why cerr:s everywhere, instead of cout:s? Well, cerr is not buffered.
  202. */
  203.  
  204. unsigned long    timeStart;                // global timing
  205.  
  206. void TRandom::TestRandomClass()
  207. {
  208. //    local variables
  209.  
  210.     const short     cARRAYSIZE = 80;                // 200 is a nice size
  211.     const long        cBIGNUM = 1000;                    //cBIGNUM= 1000000 takes about 40 sec
  212.  
  213.     unsigned short     val;
  214.     long            x;
  215.     unsigned short    array1[cARRAYSIZE], array2[cARRAYSIZE];
  216.  
  217.     InitGraf((Ptr) &qd.thePort);            // Initialize grafport!
  218.  
  219.  
  220. //    First initial quick test of the toolbox value
  221.  
  222.     qd.randSeed = TickCount();
  223.     long xx = Random();
  224.     cerr << "Normal Toolbox Random     = " << xx << '\n';
  225.  
  226.     
  227. //    1. Create an instance of each TRandom class -----------------------------
  228.     
  229.     TRandom aRandom;    
  230.     val = aRandom.Next();                    
  231.     cerr << "Toolbox aRandom.Next    = " << val << "\n";
  232.  
  233.  
  234.     aRandom.SetRandomGenerator(TRandom::QUICK);
  235.     val = aRandom.Next();
  236.     cerr <<"Quick aRandom.Next        = " << val << '\n';
  237.  
  238.  
  239.     aRandom.SetRandomGenerator(TRandom::SHUFFLE);
  240.     val = aRandom.Next();
  241.     cerr <<"Shuffle aRandom.Next    = " << val << '\n';
  242.  
  243.     aRandom.SetRandomGenerator(TRandom::PM);
  244.     val = aRandom.Next();
  245.     cerr <<"PM aRandom.Next            = " << val << '\n';
  246.  
  247. //     2. Efficiency test, docBIGNUMtimes random numbers and return the time
  248.  
  249.     cerr << "Doing " <<cBIGNUM<<" random numbers of each class...this will take some time\n";
  250.  
  251. // Toolbox Random    
  252.  
  253.     aRandom.SetRandomGenerator(TRandom::MACOS);
  254.     GetDateTime(&timeStart);
  255.     for(x = 0; x <= cBIGNUM; x++){
  256.         val = aRandom.Next();
  257.         #if DEBUG
  258.         cerr << "Toolbox Random " << x <<" = " << val << '\n';
  259.         #endif
  260.         SpinCursor(1);
  261.     }
  262.     CalcTime("Toolbox");
  263.  
  264.  
  265.  
  266. // Quick Random    
  267.  
  268.     aRandom.SetRandomGenerator(TRandom::QUICK);
  269.     GetDateTime(&timeStart);
  270.     for(x = 0; x <= cBIGNUM; x++){
  271.         val = aRandom.Next();
  272.         #if DEBUG
  273.         cerr << "Quick Random " << x <<" = " << val << '\n';
  274.         #endif
  275.         SpinCursor(1);
  276.     }
  277.     CalcTime("Quick");
  278.  
  279.  
  280. // Shuffle Random    
  281.  
  282.     aRandom.SetRandomGenerator(TRandom::SHUFFLE);
  283.     GetDateTime(&timeStart);
  284.     for(x = 0; x <= cBIGNUM; x++){
  285.         val = aRandom.Next();
  286.         #if DEBUG
  287.         cerr << "Shuffle Random " << x <<" = " << val << '\n';
  288.         #endif
  289.         SpinCursor(1);
  290.     }
  291.     CalcTime("Shuffle");
  292.  
  293.  
  294. // PM Random
  295.  
  296.     aRandom.SetRandomGenerator(TRandom::PM);
  297.     GetDateTime(&timeStart);
  298.     for(x = 0; x <= cBIGNUM; x++){
  299.         val = aRandom.Next();
  300.         #if DEBUG
  301.         cerr << "PM Random " << x <<" = " << val << '\n';
  302.         #endif
  303.         SpinCursor(1);
  304.     }
  305.     CalcTime("PM");
  306.     
  307.  
  308. //    3. Performance test, create twice the random numbers with the same
  309. //    original seed, and compare the results, signal if they differ
  310.  
  311.     long definedSeed;
  312.  
  313.     cerr << "Performance test, create from same seed twice and compare...\n";
  314.     
  315.  
  316. //    MACOS Random Performance test
  317.  
  318.     cerr <<"MacOS Random...";
  319.     aRandom.SetRandomGenerator(TRandom::MACOS);
  320.  
  321.     aRandom.ShuffleSeed();                        // get new seed
  322.     definedSeed = aRandom.GetSeedValue();        // store it
  323.  
  324.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  325.     
  326.     for(x = 0; x < cARRAYSIZE; x++)                // fill array1
  327.         array1[x] = aRandom.Next();
  328.  
  329.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  330.     for(x = 0; x < cARRAYSIZE; x++)                // fill array2
  331.         array2[x] = aRandom.Next();
  332.         
  333.     for(x = 0; x < cARRAYSIZE; x++){                // compare
  334.         if(array1[x] != array2[x]){
  335.             cerr << "problems with Toolbox values....\n";
  336.             cerr << "x = " << x <<",array1 = " << array1[x] 
  337.                 << ", array2 = " << array2[x] << '\n';
  338.         } else cerr <<".";
  339.     }
  340.     cerr <<"\n";
  341.  
  342.  
  343. //    Quick Random Performance test
  344.  
  345.     cerr <<"Quick Random...";
  346.     aRandom.SetRandomGenerator(TRandom::QUICK);
  347.  
  348.     aRandom.ShuffleSeed();                        // get new seed
  349.     definedSeed = aRandom.GetSeedValue();        // store it
  350.  
  351.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  352.     
  353.     for(x = 0; x < cARRAYSIZE; x++)                // fill array1
  354.         array1[x] = aRandom.Next();
  355.  
  356.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  357.     for(x = 0; x < cARRAYSIZE; x++)                // fill array2
  358.         array2[x] = aRandom.Next();
  359.         
  360.     for(x = 0; x < cARRAYSIZE; x++){                // compare
  361.         if(array1[x] != array2[x]){
  362.             cerr << "problems with Quick values....\n";
  363.             cerr << "x = " << x <<",array1 = " << array1[x] 
  364.                 << ", array2 = " << array2[x] << '\n';
  365.         } else cerr <<".";
  366.     }
  367.     cerr <<"\n";
  368.     
  369.  
  370.  
  371. //    Shuffle Random Performance test
  372.  
  373.     cerr <<"Shuffle Random...";
  374.     TRandom rand1(TRandom::SHUFFLE);
  375.     TRandom rand2(TRandom::SHUFFLE);
  376.  
  377.     aRandom.ShuffleSeed();                        // get new seed
  378.     definedSeed = aRandom.GetSeedValue();        // store it
  379.  
  380.     rand1.SetSeedValue(definedSeed);            // back to first seed
  381.     
  382.     for(x = 0; x < cARRAYSIZE; x++)                // fill array1
  383.         array1[x] = rand1.Next();
  384.  
  385.     rand2.SetSeedValue(definedSeed);            // back to first seed
  386.     for(x = 0; x < cARRAYSIZE; x++)                // fill array2
  387.         array2[x] = rand2.Next();
  388.         
  389.     for(x = 0; x < cARRAYSIZE; x++){                // compare
  390.         if(array1[x] != array2[x]){
  391.             cerr << "problems with Quick values....\n";
  392.             cerr << "x = " << x <<",array1 = " << array1[x] 
  393.                 << ", array2 = " << array2[x] << '\n';
  394.         } else cerr <<".";
  395.     }
  396.     cerr <<"\n";
  397.     
  398.  
  399.  
  400.  
  401. //    Park-Miller
  402.  
  403.     cerr <<"PM Random...";
  404.     aRandom.SetRandomGenerator(TRandom::PM);
  405.  
  406.     aRandom.ShuffleSeed();                        // get new seed
  407.     definedSeed = aRandom.GetSeedValue();        // store it
  408.  
  409.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  410.     
  411.     for(x = 0; x < cARRAYSIZE; x++)                // fill array1
  412.         array1[x] = aRandom.Next();
  413.  
  414.     aRandom.SetSeedValue(definedSeed);            // back to first seed
  415.  
  416.     for(x = 0; x < cARRAYSIZE; x++)                // fill array2
  417.         array2[x] = aRandom.Next();
  418.         
  419.     for(x = 0; x < cARRAYSIZE; x++){                // compare
  420.         if(array1[x] != array2[x]){
  421.             cerr << "problems with PM values....\n";
  422.             cerr << "x = " << x <<",array1 = " << array1[x] 
  423.                 << ", array2 = " << array2[x] << '\n';
  424.         } else cerr <<".";
  425.     }
  426.     cerr <<"\n";
  427.  
  428.  
  429. //    4. Test mutator class reference passing (syntax check) --------------
  430.  
  431.     aRandom.SetRandomGenerator(TRandom::MACOS).ShuffleSeed();
  432.  
  433.  
  434. //    5. Test of copy constructor -----------------------------------------
  435.  
  436.     cerr <<"\nTest of copy constructor\n";
  437.     
  438.     TRandom bRandom(aRandom);
  439.  
  440.     cerr << "Seed from aRandom = " << aRandom.GetSeedValue() << "\n";
  441.     cerr << "Seed from bRandom = " << bRandom.GetSeedValue() << "\n";
  442.     cerr << "Rand val from aRandom = " << aRandom.Next() << "\n";
  443.     cerr << "Rand val from bRandom = " << bRandom.Next() << "\n";
  444.  
  445.  
  446. //     6. Test of assignment operator overload
  447.  
  448.     cerr <<"\nTest of assignment operator overload\n";
  449.  
  450.     TRandom cRandom = aRandom;
  451.  
  452.     cerr << "Seed from aRandom = " << aRandom.GetSeedValue() << "\n";
  453.     cerr << "Seed from cRandom = " << cRandom.GetSeedValue() << "\n";
  454.     cerr << "Rand val from aRandom = " << aRandom.Next() << "\n";
  455.     cerr << "Rand val from cRandom = " << cRandom.Next() << "\n";
  456.     
  457. //    the end -------------------------------------------------------------
  458.  
  459.     cerr <<"The end of the TRandom Test!\n";
  460.  
  461. }
  462.  
  463. // calculate Time
  464.  
  465. void  TRandom::CalcTime(const char* string)
  466. {
  467.     unsigned long totalTime, timeEnd;
  468.     
  469.     GetDateTime(&timeEnd);
  470.     totalTime = timeEnd - timeStart;
  471.     cerr <<"Time for \t" << string <<"\t= " << totalTime <<'\n';
  472. }
  473.  
  474. // THE END ----------------------------------------------------------------------------